#include "formSocketSrv.h"
#include "ui_formSocketSrv.h"
#include <QMessageBox>

FormSocketSrv::FormSocketSrv(QWidget *parent, int socketType) :
    QWidget(parent),
    ui(new Ui::FormSocketSrv)
{
    ui->setupUi(this);

    m_barrPacket.clear();
    m_nPackIndex = 0;
    m_nPackLength = 0;
    m_nPackChecksum = 0;

    m_pCtrlMouse = new ctrlMouse(this);
    connect(this, SIGNAL(sigCtrlMouse(QByteArray)), m_pCtrlMouse, SLOT(slotCtrlMouse(QByteArray)));

    m_nPort = 11000;
    m_nSocketType = socketType;
    m_pUdpSocket = new QUdpSocket(this);
    m_pTcpServer = new QTcpServer(this);

    showHostIP();
}

FormSocketSrv::~FormSocketSrv()
{
    delete ui;

    if (m_pCtrlMouse != NULL)
    {
        delete m_pCtrlMouse;
        m_pCtrlMouse = NULL;
    }
    if (m_pUdpSocket != NULL)
    {
        delete m_pUdpSocket;
        m_pUdpSocket = NULL;
    }
}

void FormSocketSrv::showHostIP()
{
    QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName());
    foreach(QHostAddress address, info.addresses())
    {
        if (address.protocol() == QAbstractSocket::IPv4Protocol)
        {
            ui->lwIP->addItem(address.toString());
        }
    }
}

void FormSocketSrv::on_btnStart_clicked()
{
    if (ui->btnStart->text() == tr("Start"))
    {
        if (ui->lePort->text() == "")
        {
            ui->lePort->setText("11000");
            m_nPort = 11000;
        }
        else
        {
            m_nPort = ui->lePort->text().toInt();
        }

        startServer(true);
        emit sigSrvStateChanged(true);
    }
    else
    {
        startServer(false);
        emit sigSrvStateChanged(false);
    }
}

void FormSocketSrv::startServer(bool state)
{
    if (state)
    {
        if (m_nSocketType == 0) //udp
        {
            m_pUdpSocket->bind(QHostAddress::Any, m_nPort);
            connect(m_pUdpSocket, SIGNAL(readyRead()), this, SLOT(slotReadUdpData()));
        }
        else    //tcp
        {
            if (!m_pTcpServer->listen(QHostAddress::Any, m_nPort))
            {
                //listen fail
                qDebug()<<m_pTcpServer->errorString();
                QMessageBox::information(this, tr("Listen Fail"), m_pTcpServer->errorString());
            }

            connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(slotConnectClient()));
        }

        ui->btnStart->setText(tr("Stop"));
        ui->lePort->setEnabled(false);
    }
    else
    {
        if (m_nSocketType == 0) //udp
            m_pUdpSocket->close();
        else    //tcp
            m_pTcpServer->close();

        ui->btnStart->setText(tr("Start"));
        ui->lePort->setEnabled(true);
    }
}

void FormSocketSrv::slotConnectClient()
{
    m_pConnectSocket = m_pTcpServer->nextPendingConnection();
    connect(m_pConnectSocket, SIGNAL(readyRead()), this, SLOT(slotReadTcpData()));
    connect(m_pConnectSocket, SIGNAL(disconnected()),
            m_pConnectSocket, SLOT(deleteLater()));
    connect(m_pConnectSocket, SIGNAL(disconnected()),
            this, SLOT(slotDisconnected()));
}

void FormSocketSrv::slotDisconnected()
{
    qDebug()<<__func__;
}

void FormSocketSrv::slotReadTcpData()
{
    QByteArray byteArray;

    byteArray = m_pConnectSocket->readAll();
    processPakcet(byteArray);
}

void FormSocketSrv::slotReadUdpData()
{
    QByteArray byteArray;
    while (m_pUdpSocket->hasPendingDatagrams())
    {
        byteArray.resize(m_pUdpSocket->pendingDatagramSize());
        m_pUdpSocket->readDatagram(byteArray.data(), byteArray.size());

        processPakcet(byteArray);
    }
}

//process packet to completing packet
void FormSocketSrv::processPakcet(QByteArray byteArray)
{
    int i=0;

    //Flag(1)  data len(1) checksum(1) main cmd(1)  sub cmd(2) data(len-6)
    for (i = 0; i < byteArray.length(); i++)
    {
        if (m_nPackIndex < m_nPackLength && m_nPackLength > 0 && m_nPackIndex > 0)
        {
            m_barrPacket.append(byteArray.at(i));
            m_nPackIndex++;

            if (m_nPackIndex == m_nPackLength)
            {
                if (isCompletePacket(m_barrPacket))
                {
                    handlePakcet(m_barrPacket);
                }
            }
        }
        else if (m_nPackIndex == 1)
        {
            m_barrPacket.append(byteArray.at(i));
            m_nPackLength = byteArray.at(i) & 0xff;
            m_nPackIndex++;
        }
        else if (m_nPackIndex == 2)
        {
            m_barrPacket.append(byteArray.at(i));
            m_nPackChecksum = byteArray.at(i) & 0xff;
            m_nPackIndex++;
        }
        else if ((byteArray.at(i) & 0xff) == 0xfe)
        {
            m_nPackIndex = 0;
            m_nPackLength = 0;
            m_nPackChecksum = 0;
            m_barrPacket.clear();
            m_barrPacket.append(byteArray.at(i));
            m_nPackIndex++;
        }
        else
        {
        }
    }
}

void FormSocketSrv::handlePakcet(QByteArray byteArray)
{
    //Flag(1)  data len(1) checksum(1) main cmd(1)  sub cmd(2) data(len-6)
#if 0
    qDebug("len=%d, %x %x %x %x %x %x",byteArray.length(),
           byteArray.at(0),byteArray.at(1),byteArray.at(2),
           byteArray.at(3),byteArray.at(4),byteArray.at(5));
#endif
    //main command
    switch(byteArray.at(3) & 0xff)
    {
    case MCMD_INPUT:
        if ((byteArray.at(4) & 0xff) == SCMD_MOUSE)
            emit sigCtrlMouse(byteArray);
        break;
    }
}

//judeg whether the packet is complete
bool FormSocketSrv::isCompletePacket(QByteArray byteArray)
{
    int i, nChecksum;

    if (byteArray.length() <= 0)
        return false;

    nChecksum = 0;
    for (i = 3; i < byteArray.length(); i++)
    {
        nChecksum = nChecksum + (byteArray.at(i) & 0xff);
    }

    if ((nChecksum & 0xff) == (int)(byteArray.at(2) & 0xff))
        return true;

    return false;
}


